package com.hopes.bizz.protocol.hj212.server.handler;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hopes.bizz.common.core.util.CRCUtils;
import com.hopes.bizz.protocol.hj212.activemq.producer.ActiveMqQueueSender;
import com.hopes.bizz.protocol.hj212.bo.HJ212MainAttrBO;
import com.hopes.bizz.protocol.hj212.constant.HJ212Constant;
import com.hopes.bizz.protocol.hj212.log.ProtocolLogger;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.hopes.bizz.protocol.hj212.constant.HJ212Constant.*;

@Component
@RefreshScope
@Slf4j
public class AbstractHJ212DataHandler implements HJ212DataHandler {
    @Autowired
    private ActiveMqQueueSender activeMqQueueSender;
    @Autowired
    private ProtocolLogger protocolLogger;
    /**
     * 212协议数据
     */
    public static final String PATTERN_212 = "^##\\d{4}.+&&.{4}(\r\n)*$";
    public static final String REDIS_KEY_PRE = "HJ212:";
    public static final String REDIS_KEY_LATEST_DATA = "LATEST:";
    public static final String REDIS_KEY_SAFETY_LATEST_DATA = "SAFETY_LATEST:";
    /**
     * 需要替换报文字段
     */
    private Map<String , String> translationMap;
    @Value("#{${hj212.translationMap:{}}}")
    public void setTranslationMap(Map<String, String> translationMap) {
        this.translationMap = translationMap ;
    }

    @Override
    public boolean handler(String data, DataHandlerChain chain) {
        Date receiveTime = new Date();
        if (!StringUtil.isNullOrEmpty(data)) {
            String[] dataArr = data.split("\r\n");
            for (String tempData : dataArr) {
                long start = System.currentTimeMillis();
                if (tempData.length() > 10) {
                    if (isHJ212Protocol(tempData)) {
                        Map<String, String> dataMap = hj212DataToMap(tempData);
                        String commandNo = dataMap.get(HJ212Constant.KEY_COMMAND_NO);
                        if (StringUtil.isNullOrEmpty(commandNo)) {
                            log.error(HJ212Constant.KEY_COMMAND_NO + " 不能为空");
                        }

                        // 组装消息对象
                        HJ212MainAttrBO mainAttrBO = new HJ212MainAttrBO();
                        buildMainAttr(mainAttrBO, dataMap, commandNo);

                        String msg = JSONObject.toJSONString(mainAttrBO);
                        // 发送消息
                        activeMqQueueSender.sendHj212Msg(msg);
                        log.info("发送mq消息: {}", msg);
                        protocolLogger.saveHj212PacketLog(data, receiveTime, true, "成功",
                                msg, Math.toIntExact(System.currentTimeMillis() - start));
                        return true;
                    }
                    protocolLogger.saveHj212PacketLog(data, receiveTime, false, "数据不符合212标准",
                            null, Math.toIntExact(System.currentTimeMillis() - start));
                }
                protocolLogger.saveHj212PacketLog(data, receiveTime, false, "数据长度小于10",
                        null, Math.toIntExact(System.currentTimeMillis() - start));
            }
        }
        return chain.handler(data, chain);
    }

    /**
     * 构建主要参数
     *
     * @param mainAttrBO
     * @param dataMap
     */
    private void buildMainAttr(HJ212MainAttrBO mainAttrBO, Map<String, String> dataMap, String commandNo) {
        mainAttrBO.setMn(dataMap.get(KEY_MN));
        mainAttrBO.setCn(commandNo);
        mainAttrBO.setQn(dataMap.get(KEY_REQUEST_NO));
        mainAttrBO.setSt(dataMap.get(KEY_SYSTEM_NO));
        mainAttrBO.setTime(HJ212MainAttrBO.findDataTime(dataMap, commandNo));
        mainAttrBO.setData(buildJSONArrayData(dataMap));
    }

    private JSONArray buildJSONArrayData(Map<String, String> dataMap) {
        // Step.1 去除多余属性
        dataMap.remove(KEY_MN);
        dataMap.remove(KEY_COMMAND_NO);
        dataMap.remove(KEY_REQUEST_NO);
        dataMap.remove(KEY_SYSTEM_NO);
        dataMap.remove(KEY_CP);
        dataMap.remove(KEY_COMMAND_PW);
        dataMap.remove(KEY_DATA_TIME);
        dataMap.remove(KEY_FLAG);
        dataMap.remove(KEY_LA);

        // Step.2 先分类
        Map<String, JSONObject> factorDataMap = new HashMap<>();
        Iterator<Map.Entry<String, String>> entryIterator = dataMap.entrySet().iterator();
        JSONObject dataJson = new JSONObject();
        while (entryIterator.hasNext()) {
            Map.Entry<String, String> entry = entryIterator.next();
            String key = entry.getKey();
            if (key.contains("-")) {
                String valueStr = entry.getValue();
                String[] keys = key.split("-");
                if (keys.length == FACTOR_KEY_SIZE) {
                    String factorCode = keys[FACTOR_KEY_INDEX];
                    String dataAttr = keys[FACTOR_ATTR_INDEX];
                    JSONObject dataItem = factorDataMap.get(factorCode);

                    if (dataItem == null) {
                        dataItem = new JSONObject();
                        factorDataMap.put(factorCode, dataItem);
                        dataItem.put(DATA_ITEM_ATTR_KEY, factorCode);
                        dataJson.put(factorCode, dataItem);
                    }

                    dataItem.put(dataAttr, valueStr);
                }
            }
        }

        // Step.2 组装JSONArray
        JSONArray jsonArray = new JSONArray();
        Set<String> translation = translationMap.keySet();
        for (String factorCode : dataJson.keySet()) {
            JSONObject data = new JSONObject();
            data.put("key", factorCode);
            JSONObject dataItem = dataJson.getJSONObject(factorCode);
            for (String field : dataItem.keySet()) {
                if (translation.contains(field)) {
                    data.put(translationMap.get(field), dataItem.get(field));
                } else {
                    data.put(field.toLowerCase(), dataItem.get(field));
                }
            }
            jsonArray.add(data);
        }

        return jsonArray;
    }

    /**
     * 212协议数据转换为Map对象
     * @param data
     * @return
     */
    public static Map<String, String> hj212DataToMap(String data) {
        String tempData = data.substring(6);
        Map<String, String> dataMap = new HashMap<>();
        String regex = "(.+?)=(.*?)(,|;|(&&))";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(tempData);
        while (m.find()) {
            dataMap.put(m.group(1), m.group(2));
        }

        return dataMap;
    }

    private boolean isHJ212Protocol(String data) {
        //判断是否符合212标准: ##开头 四位数字 N个字符 &&加四位字符结尾
        return data.matches(PATTERN_212) && isValidCRC(data);
    }

    /**
     * 校验是否通过crc校验
     *
     * @param data
     * @return
     */
    private boolean isValidCRC(String data) {
        String crcBody = data.substring(6, data.length() - 4);
        String crcCode = data.substring(data.length() - 4);
        String checkCode = CRCUtils.getCRC16(crcBody);
        boolean valid = checkCode.equalsIgnoreCase(crcCode);
        log.debug("CRC校验结果, crcCode={}, checkCode={}, valid={}", crcCode, checkCode, valid);
        return valid;
    }
}
